package cz.muni.fi.pb138.eis_core;

import java.util.LinkedList;
import java.util.List;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQResultSequence;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Implementation of the ExpositionManager
 * over an XML Database (BaseX)
 * 
 * @author Jakub Senko
 */
public class ExpositionManagerImpl implements ExpositionManager
{
    DBTools dbt;
    
    public ExpositionManagerImpl(DBTools dbt)
    {
        if(dbt == null)
        {
            throw new NullPointerException();
        }
        this.dbt = dbt;
    }

    @Override
    public void create(ExpositionEntity entity) throws XQException
    {
        if(entity == null || "".equals(entity.getName()))
        {
            throw new NullPointerException();
        }
        
        Query q = dbt.getQuery();
        
        XQResultSequence xqrs = q.execute(dbt.getDoc()
                + "//lastId/exposition");
        
        xqrs.next();
        
        long id = Long.parseLong(xqrs.getNode().getTextContent()) + 1;

        dbt.executeQueryCommand("replace value of node "
                + dbt.getDoc() + "//lastId/exposition with '" + id + "'");
        
        dbt.executeQueryCommand(
            "insert node "
                + "<exposition id='" + id + "'>"
                    + "<name>" + dbt.sanitize(entity.getName()) + "</name>"
                    + "<artworks/>"
                + "</exposition>"
            + " into " + dbt.getDoc() + "//expositions"
        );
        
        entity.setId(id);
        
        q.close();
    }

    @Override
    public ExpositionEntity getById(long id) throws XQException
    {       
        if(id <= 0) return null;
        
        Query q = dbt.getQuery();
        
        XQResultSequence xqrs = q.execute(
                dbt.getDoc() + "//exposition[@id = '" + id + "']");
        
        // does the entity exist?        
        if(xqrs.next() == false)
        {
            return null;
        }
       
        ExpositionEntity e = parse(xqrs.getNode());
        
        q.close();
        
        return e;
    }

    @Override
    public List<ExpositionEntity> getAll() throws XQException
    {
        List<ExpositionEntity> list = new LinkedList<ExpositionEntity>();
        
        Query q = dbt.getQuery();
        
        XQResultSequence xqrs = q.execute(
                "for $exposition in " + dbt.getDoc() + "//exposition "
                + "return $exposition");
        
        xqrs.next();
        
        while(xqrs.next())
        {
            list.add(parse(xqrs.getNode()));    
        }
        q.close();
        
        return list;
    }

    /**
     * Careful, deleting exposition deletes artworks!!!
     */
    @Override
    public boolean delete(ExpositionEntity entity) throws XQException
    {
        if(entity == null)
        {
            throw new NullPointerException();
        }
        
        //does the entity exist?
        if(getById(entity.getId()) == null)
        {
            return false;
        }
        
        dbt.executeQueryCommand(
                "delete nodes " + dbt.getDoc()
                + "//exposition[@id = '" + entity.getId() + "']");
        
        return true;
    }
    
    /**
     * This method parses data and creates
     * a new ExpositionEntity from an XML Node
     * (retrieved from the database).
     * Template:
     * <exposition id="ID">
     *  <name>NAME</name>
     * </exposition>
     * 
     */
    private ExpositionEntity parse(Node node)
    {
        Element element = (Element) node;
        
        ExpositionEntity e = new ExpositionEntity();
        
        e.setId(Long.parseLong( element.getAttribute("id")));
        
        e.setName( element.getElementsByTagName("name").item(0).getTextContent());
        
        return e;
    }

}
